package com.advert.service.admin;

import com.advert.dto.mail.Mail;
import com.advert.dto.mail.UserActivationMail;
import com.advert.model.advert.AdvertEntity;
import com.advert.model.security.AccessMode;
import com.advert.model.security.Role;
import com.advert.model.security.Status;
import com.advert.model.security.UserEntity;
import com.advert.provider.advert.AdvertProvider;
import com.advert.provider.security.SecurityProvider;
import com.advert.service.mail.MailService;
import com.advert.util.Event;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.*;
import org.jboss.seam.core.Events;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;

@Name("AdminService")
@Scope(ScopeType.EVENT)
@AutoCreate
public class AdminService implements Serializable {
    @In("SecurityProvider")
    private SecurityProvider securityProvider;
    @In("AdvertProvider")
    private AdvertProvider advertProvider;
    @In("MailService")
    private MailService mailService;
    @In("executorService")
    private ExecutorService executorService;


    public List<UserEntity> getUsersByRole(Role role) {
        Events.instance().raiseEvent(Event.CLASS_ACCESS, UserEntity.class, AccessMode.ADMIN);

        return securityProvider.getUsersByRole(role);
    }

    @Transactional
    public void updateUsersRole(List<UserEntity> users) {
        Events.instance().raiseEvent(Event.CLASS_ACCESS, UserEntity.class, AccessMode.ADMIN);

        for (UserEntity user : users) {
            securityProvider.updateUser(user);
        }
    }
    
    @Transactional
    public void approveAdvert(AdvertEntity advert) {
        Events.instance().raiseEvent(Event.CLASS_ACCESS, AdvertEntity.class, AccessMode.ADMIN);

        advert.setStatus(Status.APPROVED);
        advertProvider.updateAdvert(advert);
    }

    @Transactional
    public void rejectAdvert(AdvertEntity advert) {
        Events.instance().raiseEvent(Event.CLASS_ACCESS, AdvertEntity.class, AccessMode.ADMIN);

        advert.setStatus(Status.REJECTED);
        advertProvider.updateAdvert(advert);
    }

    public void notifyAboutPendingAdvert() {
        List<UserEntity> admins = securityProvider.getUsersByRole(Role.ADMIN);
        List<Mail> mails = new ArrayList<Mail>();
        for (UserEntity admin : admins) {
            Mail mail = new Mail(admin.getUserInfo().getEmail(), "ADMIN_NOTIFY_MAIL_SUBJ", "ADMIN_NOTIFY_MAIL_BODY");
            Events.instance().raiseEvent(Event.MAIL_BUILD_REQUIRED, mail);
            mails.add(mail);
        }
        executorService.submit(new NotificationCallable(mailService, mails));
    }

    
    private class NotificationCallable implements Runnable {
        private MailService mailService;
        private List<Mail> mails;

        private NotificationCallable(MailService mailService, List<Mail> mails) {
            this.mailService = mailService;
            this.mails = mails;
        }

        public void run() {
            for (Mail mail : mails) {
                mailService.sendMail(mail);
            }
        }
    }

}
